package cn.itsource.wechart.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.itsource.basic.util.AjaxResult;
import cn.itsource.basic.util.RedisService;
import cn.itsource.config.exception.BusinessException;
import cn.itsource.org.domain.User;
import cn.itsource.org.mapper.UserMapper;
import cn.itsource.org.service.IUserService;
import cn.itsource.org.vo.LoginVo;
import cn.itsource.wechart.mapper.WxUserMapper;
import cn.itsource.wechart.pojo.domain.WechartProperties;
import cn.itsource.wechart.pojo.domain.WxUser;
import cn.itsource.wechart.pojo.dto.BinderDto;
import cn.itsource.wechart.pojo.dto.WechartTokenDto;
import cn.itsource.wechart.pojo.dto.WechartUserInfoDto;
import cn.itsource.wechart.service.IWeChartService;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

/**
 * 微信业务
 */
@Service
public class WechartServiceImpl implements IWeChartService {

    @Autowired
    private WechartProperties wechartProperties;

    @Autowired
    private WxUserMapper wxUserMapper;

    @Autowired
    private IUserService userService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisService redisService;

    @Override
    public String toLogin() {
        //https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_login&state=%s#wechat_redirect"

        //步骤一，跳转到扫描的页码
        //1.获取到url
        String codeUrl = wechartProperties.getAuthorizationCodeUrl();
        //2.进行String format操作
        String s = String.format(codeUrl, wechartProperties.getAppId(), wechartProperties.getRedirectUri(), IdUtil.fastSimpleUUID());
        //3.重定向
        return "redirect:"+s;
    }

    @Override
    public String callback(String code) {
        //步骤二，通过code获取access_token
        //1.拿到获取token的url
        //https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code
        String tokenUrl = wechartProperties.getTokenUrl();

        //2.拼接url，替换%s
        tokenUrl = String.format(tokenUrl,wechartProperties.getAppId(),wechartProperties.getAppSecrect(), code);

        //3.用java代码访问这个拼接好的url
        String result = HttpUtil.get(tokenUrl);
        //{"access_token":"61_RUM4lyYfxVfPoZksYK6Drdm-QnncltDoL83jkk8CL1mk4eE90IZjCeG7aA3_5pknRtT_x3ls9MONxIozDDc62npZs3WnsTVPVQaB5iOq3Tk","expires_in":7200,"refresh_token":"61_we-NEY4GboccEhfSVDwkKMYznOJw7gvbE5kvsTAZY14oLKLc9fk8bWjRjzvt6ogRy9jkwS5uUzgjGs_AK6PzaptPOYqvJFeXINVNNLAVCFw","openid":"oa9wA090OrSqsxy8AHbPk1qxc2uM","scope":"snsapi_login","unionid":"ovnCWw7rqhgKc0LcWhi9rPRmhb4s"}
        System.out.println(result);
        //4.把json字符串的数据封装到dto中
        WechartTokenDto wechartTokenDto = JSONObject.parseObject(result, WechartTokenDto.class);
        System.out.println(wechartTokenDto); //包含 access_token和openid

        //步骤三，获取微信三方用户信息
        //1.获取url //https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s"
        String userinfoUrl = wechartProperties.getUserinfoUrl();
        //2.处理%s
        userinfoUrl = String.format(userinfoUrl, wechartTokenDto.getAccess_token(), wechartTokenDto.getOpenid());

        //3.发get请求获取用户的信息
        String infoResult = HttpUtil.get(userinfoUrl);
        System.out.println(infoResult);//json串 openid：唯一标识

        //4.解析json字符串，到dto中
        WechartUserInfoDto infoDto = JSONObject.parseObject(infoResult, WechartUserInfoDto.class);

        System.out.println(infoDto);

        //----------------------------上面是调用微信开放平台接口，下面把微信信息绑定平台账户----------------------------------------------------------------
        /**
         * openid在每个企业账户下，每个人是唯一的，同一个人在同一个企业账号下扫描openid就是独一无二的
         * 通过分析，得到3种情况进行处理
         *   1.通过openid在t_wxuser表拿不到数据源
         *     1.1新增t_wxuser的一行数据
         *     1.2去绑定页面进行绑定
         *   2.所有的数据都是ok的 t_wxuser有user_id  t_user有手机号
         *     1.2跳转到平台首页
         *   3.其他情况
         *      3.1全部去绑定页面（binder.html）
         */
        String binderHtmlUrl = "http://localhost:8081/binder.html";

        //1.获取openid，根据openid匹配数据
        String openid = infoDto.getOpenid();
        WxUser wxUser = wxUserMapper.findByOpenid(openid);
        //2.判断微信user是否存在
        if (wxUser == null){
            WxUser dbWxUser = BeanUtil.copyProperties(infoDto, WxUser.class);
            //入库
            wxUserMapper.insertSelective(dbWxUser);
            //跳转到绑定页面
            return "redirect:"+binderHtmlUrl+"?openid="+openid;
        }

        //处理情况2
        Long userId = wxUser.getUserId();
        if (userId != null){
            //1.查user对象
            User dbUser = userService.findOne(userId);
            //2.如果数据完整
            if (dbUser != null && StrUtil.isNotBlank(dbUser.getPhone())){
                //需要穿token和登录信息
                //生成token，存到redis，返回页面
                String token = IdUtil.fastSimpleUUID();
                LoginVo loginVo = new LoginVo();
                loginVo.setToken(token);
                redisService.setStringKeyAndValue(token,loginVo,30);

                return "redirect:http://localhost:8081/index.html?phone="+dbUser.getPhone()+"&token="+token;
            }
        }

        //其他情况全部去绑定页面
        return "redirect:"+binderHtmlUrl+"?openid="+openid;
    }

    @Override
    public AjaxResult binder(BinderDto binderDto) {
        //0.验证code
        if (!StrUtil.equals(binderDto.getCode(),redisService.getKeyStringValue(binderDto.getPhone()))){
            throw new BusinessException("验证码错误");
        }

        //1.获取phone ，通过phone获取user对象
        String phone = binderDto.getPhone();
        User dbPhone = userMapper.findByPhone(phone);
        //2.份两种情况
        //dbPhone不存在 1.新增user数据  2.拿到自增id  3.修改wxUser的user_id
        Long userId = null;
        if (dbPhone == null){
            User user = new User();
            user.setPhone(phone);
            user.md5Pwd();//加盐加密
            userMapper.insertSelective(user);
            userId = user.getId();
        }else{
            userId = dbPhone.getId();
        }

        //存在，拿到userId,修改wxUser的user_id
        wxUserMapper.updateUserIdByOenid(userId,binderDto.getOpenid());

        //生成token，存到redis，返回页面
        String token = IdUtil.fastSimpleUUID();
        LoginVo loginVo = new LoginVo();
        loginVo.setPhone(phone);
        loginVo.setToken(token);
        redisService.setStringKeyAndValue(token,loginVo,30);

        return AjaxResult.createSuccess(loginVo);
    }
}
